#!/usr/bin/env python
# -*- coding: utf-8 -*-

import tkinter as tk
from tkinter import ttk, messagebox, filedialog, scrolledtext
import os
import threading
from datetime import datetime

class MainWindow:
    """主窗口类"""
    
    def __init__(self, root, backup_manager):
        self.root = root
        self.backup_manager = backup_manager
        
        # 创建UI
        self.setup_ui()
        
        # 加载任务
        self.load_tasks()
        
        # 启动UI更新线程
        self.start_ui_update_thread()
    
    def setup_ui(self):
        """设置UI"""
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建标签页
        self.notebook = ttk.Notebook(main_frame)
        self.notebook.pack(fill=tk.BOTH, expand=True)
        
        # 任务管理页
        self.tasks_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.tasks_frame, text="任务管理")
        self.setup_tasks_tab()
        
        # 添加任务页
        self.add_task_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.add_task_frame, text="添加任务")
        self.setup_add_task_tab()
        
        # 日志查看页
        self.logs_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.logs_frame, text="备份日志")
        self.setup_logs_tab()
        
        # 设置页
        self.settings_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.settings_frame, text="设置")
        self.setup_settings_tab()
    
    def setup_tasks_tab(self):
        """设置任务管理页"""
        # 工具栏
        toolbar_frame = ttk.Frame(self.tasks_frame)
        toolbar_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Button(toolbar_frame, text="刷新", command=self.load_tasks).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(toolbar_frame, text="运行选中任务", command=self.run_selected_task).pack(side=tk.LEFT, padx=5)
        ttk.Button(toolbar_frame, text="停止选中任务", command=self.stop_selected_task).pack(side=tk.LEFT, padx=5)
        ttk.Button(toolbar_frame, text="删除选中任务", command=self.delete_selected_task).pack(side=tk.LEFT, padx=5)
        
        # 任务列表
        self.tasks_tree = ttk.Treeview(
            self.tasks_frame,
            columns=("name", "source", "repo", "status", "progress", "last_backup"),
            show="tree headings"
        )
        
        # 设置列标题
        self.tasks_tree.heading("#0", text="ID")
        self.tasks_tree.heading("name", text="任务名称")
        self.tasks_tree.heading("source", text="源目录")
        self.tasks_tree.heading("repo", text="仓库地址")
        self.tasks_tree.heading("status", text="状态")
        self.tasks_tree.heading("progress", text="进度")
        self.tasks_tree.heading("last_backup", text="最后备份")
        
        # 设置列宽
        self.tasks_tree.column("#0", width=50, minwidth=50)
        self.tasks_tree.column("name", width=120, minwidth=100)
        self.tasks_tree.column("source", width=150, minwidth=100)
        self.tasks_tree.column("repo", width=200, minwidth=150)
        self.tasks_tree.column("status", width=80, minwidth=60)
        self.tasks_tree.column("progress", width=80, minwidth=60)
        self.tasks_tree.column("last_backup", width=120, minwidth=100)
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(self.tasks_frame, orient=tk.VERTICAL, command=self.tasks_tree.yview)
        self.tasks_tree.configure(yscrollcommand=scrollbar.set)
        
        # 放置控件
        self.tasks_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 任务详情框架
        details_frame = ttk.LabelFrame(self.tasks_frame, text="任务详情", padding="10")
        details_frame.pack(fill=tk.X, pady=(10, 0))
        
        self.task_details_text = scrolledtext.ScrolledText(
            details_frame,
            height=6,
            wrap=tk.WORD
        )
        self.task_details_text.pack(fill=tk.BOTH, expand=True)
        
        # 绑定选择事件
        self.tasks_tree.bind("<<TreeviewSelect>>", self.on_task_select)
    
    def setup_add_task_tab(self):
        """设置添加任务页"""
        # 创建主框架
        main_frame = ttk.Frame(self.add_task_frame)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        main_frame.rowconfigure(1, weight=1)  # 设置中间行可扩展
        
        # 固定的标题框架 - 始终可见
        title_frame = ttk.LabelFrame(main_frame, text="任务配置", padding="10")
        title_frame.grid(row=0, column=0, sticky="ew", pady=(0, 10))
        
        # 创建滚动区域 - 用于表单内容
        canvas = tk.Canvas(main_frame)
        scrollbar = ttk.Scrollbar(main_frame, orient="vertical", command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)
        
        # 配置滚动
        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )
        
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)
        
        # 放置滚动区域
        canvas.grid(row=1, column=0, sticky="nsew")
        scrollbar.grid(row=1, column=1, sticky="ns")
        
        # 固定的底部按钮框架 - 始终可见
        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=2, column=0, columnspan=2, sticky="ew", pady=(10, 0))
        
# 创建表单内容框架，并确保它填充整个可滚动区域
        inner_frame = ttk.Frame(scrollable_frame)
        inner_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建表单框架
        form_frame = ttk.Frame(inner_frame, padding=10)
        form_frame.pack(fill=tk.BOTH, expand=True)
        
        # 任务名称
        ttk.Label(form_frame, text="任务名称:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.task_name_entry = ttk.Entry(form_frame, width=50)
        self.task_name_entry.grid(row=0, column=1, sticky=tk.EW, pady=5, padx=(10, 0))
        
        # 源目录
        ttk.Label(form_frame, text="源目录:").grid(row=1, column=0, sticky=tk.W, pady=5)
        source_frame = ttk.Frame(form_frame)
        source_frame.grid(row=1, column=1, sticky=tk.EW, pady=5, padx=(10, 0))
        source_frame.columnconfigure(0, weight=1)
        
        self.source_path_entry = ttk.Entry(source_frame)
        self.source_path_entry.grid(row=0, column=0, sticky=tk.EW, padx=(0, 5))
        
        ttk.Button(source_frame, text="浏览", command=self.browse_source_dir).grid(row=0, column=1)
        
        # 仓库地址
        ttk.Label(form_frame, text="仓库地址:").grid(row=2, column=0, sticky=tk.W, pady=5)
        self.repo_url_entry = ttk.Entry(form_frame, width=50)
        self.repo_url_entry.grid(row=2, column=1, sticky=tk.EW, pady=5, padx=(10, 0))
        
        # 分支
        ttk.Label(form_frame, text="分支:").grid(row=3, column=0, sticky=tk.W, pady=5)
        self.branch_entry = ttk.Entry(form_frame, width=50)
        self.branch_entry.grid(row=3, column=1, sticky=tk.EW, pady=5, padx=(10, 0))
        self.branch_entry.insert(0, "main")
        
        # 用户信息
        user_info_frame = ttk.LabelFrame(form_frame, text="Git用户信息", padding="5")
        user_info_frame.grid(row=4, column=0, columnspan=2, sticky=tk.EW, pady=10)
        user_info_frame.columnconfigure(1, weight=1)
        
        ttk.Label(user_info_frame, text="用户名:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.username_entry = ttk.Entry(user_info_frame)
        self.username_entry.grid(row=0, column=1, sticky=tk.EW, pady=5, padx=(10, 0))
        
        ttk.Label(user_info_frame, text="邮箱:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.email_entry = ttk.Entry(user_info_frame)
        self.email_entry.grid(row=1, column=1, sticky=tk.EW, pady=5, padx=(10, 0))
        
        # 计划任务
        schedule_frame = ttk.LabelFrame(form_frame, text="计划任务", padding="5")
        schedule_frame.grid(row=5, column=0, columnspan=2, sticky=tk.EW, pady=10)
        schedule_frame.columnconfigure(1, weight=1)
        
        self.scheduled_var = tk.BooleanVar()
        ttk.Checkbutton(schedule_frame, text="启用计划任务", 
                       variable=self.scheduled_var).grid(row=0, column=0, sticky=tk.W, pady=5)
        
        ttk.Label(schedule_frame, text="执行时间:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.schedule_time_entry = ttk.Entry(schedule_frame)
        self.schedule_time_entry.grid(row=1, column=1, sticky=tk.W, pady=5, padx=(10, 0))
        self.schedule_time_entry.insert(0, "03:00")
        
        # 高级选项
        options_frame = ttk.LabelFrame(form_frame, text="高级选项", padding="5")
        options_frame.grid(row=6, column=0, columnspan=2, sticky=tk.EW, pady=10)
        options_frame.columnconfigure(1, weight=1)
        
        self.incremental_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(options_frame, text="增量备份", 
                       variable=self.incremental_var).grid(row=0, column=0, sticky=tk.W, pady=5)
        
        self.resume_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(options_frame, text="断点续传", 
                       variable=self.resume_var).grid(row=1, column=0, sticky=tk.W, pady=5)
        
        self.large_file_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(options_frame, text="大文件分片", 
                       variable=self.large_file_var).grid(row=2, column=0, sticky=tk.W, pady=5)
        
        # 排除模式
        exclude_frame = ttk.LabelFrame(form_frame, text="排除模式", padding="5")
        exclude_frame.grid(row=7, column=0, columnspan=2, sticky=tk.EW, pady=10)
        
        self.exclude_text = scrolledtext.ScrolledText(exclude_frame, height=8, wrap=tk.WORD)
        self.exclude_text.pack(fill=tk.BOTH, expand=True)
        self.exclude_text.insert(tk.END, 
            ".git\n.svn\n.idea\n.vscode\n.DS_Store\n__pycache__\nnode_modules\nvendor\ncache\ntmp\nlogs\nuploads\nbackup\ntemp\nruntime\nstorage\n*.zip\n*.rar\n*.7z\n*.tar.*\n*.gz\n*.bz2\n*.log\n*.tmp\n*.sql\n*.bak\n*.cache\n*.swp\n*.pid\n*.lock\n*.sock\n*.session"
        )
        
        # 底部按钮
        ttk.Button(button_frame, text="添加任务", command=self.add_task).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="重置表单", command=self.reset_form).pack(side=tk.LEFT, padx=5)
        
        # 配置表单网格权重
        form_frame.columnconfigure(1, weight=1)
    
    def setup_logs_tab(self):
        """设置日志查看页"""
        # 工具栏
        toolbar_frame = ttk.Frame(self.logs_frame)
        toolbar_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(toolbar_frame, text="选择任务:").pack(side=tk.LEFT, padx=(0, 5))
        
        self.task_selector = ttk.Combobox(toolbar_frame, state="readonly", width=30)
        self.task_selector.pack(side=tk.LEFT, padx=(0, 10))
        
        ttk.Button(toolbar_frame, text="查看日志", command=self.view_task_log).pack(side=tk.LEFT, padx=5)
        ttk.Button(toolbar_frame, text="刷新", command=self.refresh_task_selector).pack(side=tk.LEFT, padx=5)
        ttk.Button(toolbar_frame, text="清空日志", command=self.clear_logs).pack(side=tk.LEFT, padx=5)
        
        # 日志显示区域
        self.log_text = scrolledtext.ScrolledText(
            self.logs_frame,
            wrap=tk.WORD,
            font=("Consolas", 9)
        )
        self.log_text.pack(fill=tk.BOTH, expand=True)
    
    def setup_settings_tab(self):
        """设置设置页"""
        # 全局设置框架
        settings_frame = ttk.LabelFrame(self.settings_frame, text="全局设置", padding="10")
        settings_frame.pack(fill=tk.X, padx=10, pady=10)
        settings_frame.columnconfigure(1, weight=1)
        
        # 默认Git用户信息
        ttk.Label(settings_frame, text="默认Git用户名:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.default_username_entry = ttk.Entry(settings_frame)
        self.default_username_entry.grid(row=0, column=1, sticky=tk.EW, pady=5, padx=(10, 0))
        
        ttk.Label(settings_frame, text="默认Git邮箱:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.default_email_entry = ttk.Entry(settings_frame)
        self.default_email_entry.grid(row=1, column=1, sticky=tk.EW, pady=5, padx=(10, 0))
        
        # 备份限制
        limits_frame = ttk.LabelFrame(self.settings_frame, text="备份限制", padding="10")
        limits_frame.pack(fill=tk.X, padx=10, pady=10)
        limits_frame.columnconfigure(1, weight=1)
        
        ttk.Label(limits_frame, text="最大并发备份任务数:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.max_concurrent_spinbox = ttk.Spinbox(limits_frame, from_=1, to=10, width=10)
        self.max_concurrent_spinbox.grid(row=0, column=1, sticky=tk.W, pady=5, padx=(10, 0))
        self.max_concurrent_spinbox.set(3)
        
        ttk.Label(limits_frame, text="备份超时时间(分钟):").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.timeout_spinbox = ttk.Spinbox(limits_frame, from_=10, to=120, width=10)
        self.timeout_spinbox.grid(row=1, column=1, sticky=tk.W, pady=5, padx=(10, 0))
        self.timeout_spinbox.set(60)
        
        # 保存按钮
        save_button_frame = ttk.Frame(self.settings_frame)
        save_button_frame.pack(fill=tk.X, padx=10, pady=10)
        
        ttk.Button(save_button_frame, text="保存设置", command=self.save_settings).pack(side=tk.LEFT, padx=5)
        ttk.Button(save_button_frame, text="重置设置", command=self.reset_settings).pack(side=tk.LEFT, padx=5)
    
    def load_tasks(self):
        """加载任务列表"""
        # 清空当前列表
        for item in self.tasks_tree.get_children():
            self.tasks_tree.delete(item)
        
        # 加载任务
        for task in self.backup_manager.tasks:
            status_text = ""
            if task.status == "idle":
                status_text = "空闲"
            elif task.status == "running":
                status_text = "运行中"
            elif task.status == "success":
                status_text = "成功"
            elif task.status == "failed":
                status_text = "失败"
            
            progress_text = f"{task.progress}%" if task.progress > 0 else "-"
            
            last_backup_text = "-"
            if task.last_backup:
                try:
                    dt = datetime.fromisoformat(task.last_backup)
                    last_backup_text = dt.strftime("%Y-%m-%d %H:%M")
                except:
                    last_backup_text = task.last_backup
            
            self.tasks_tree.insert(
                "",
                tk.END,
                iid=task.id,
                text=task.id[:8],
                values=(
                    task.name,
                    task.source_path,
                    task.repo_url,
                    status_text,
                    progress_text,
                    last_backup_text
                )
            )
        
        # 更新任务选择器
        self.refresh_task_selector()
    
    def refresh_task_selector(self):
        """刷新任务选择器"""
        task_names = [task.name for task in self.backup_manager.tasks]
        self.task_selector['values'] = task_names
        if task_names and not self.task_selector.get():
            self.task_selector.current(0)
    
    def on_task_select(self, event):
        """任务选择事件"""
        selection = self.tasks_tree.selection()
        if not selection:
            self.task_details_text.delete(1.0, tk.END)
            return
        
        task_id = selection[0]
        task = self.backup_manager.get_task(task_id)
        if not task:
            return
        
        # 显示任务详情
        details = f"任务名称: {task.name}"
        details += f"源目录: {task.source_path}"
        details += f"仓库地址: {task.repo_url}"
        details += f"分支: {task.branch}"
        details += f"状态: {task.status}"
        details += f"进度: {task.progress}%"
        details += f"消息: {task.message}"
        details += f"计划任务: {'是' if task.scheduled else '否'}"
        if task.scheduled:
            details += f"执行时间: {task.schedule_time}"
        details += f"增量备份: {'是' if task.incremental else '否'}"
        details += f"断点续传: {'是' if task.resume_transfer else '否'}"
        details += f"大文件分片: {'是' if task.large_file_chunk else '否'}"
        details += f"创建时间: {task.created_at}"
        if task.last_backup:
            details += f"最后备份: {task.last_backup}"
        
        self.task_details_text.delete(1.0, tk.END)
        self.task_details_text.insert(tk.END, details)
    
    def browse_source_dir(self):
        """浏览源目录"""
        directory = filedialog.askdirectory(
            title="选择源目录",
            initialdir=self.source_path_entry.get() or os.getcwd()
        )
        if directory:
            self.source_path_entry.delete(0, tk.END)
            self.source_path_entry.insert(0, directory)
    
    def add_task(self):
        """添加任务"""
        # 获取表单数据
        task_name = self.task_name_entry.get().strip()
        source_path = self.source_path_entry.get().strip()
        repo_url = self.repo_url_entry.get().strip()
        branch = self.branch_entry.get().strip()
        username = self.username_entry.get().strip()
        email = self.email_entry.get().strip()
        schedule_time = self.schedule_time_entry.get().strip()
        exclude_patterns = self.exclude_text.get(1.0, tk.END).strip()
        
        # 验证必填字段
        if not task_name:
            messagebox.showerror("错误", "请输入任务名称")
            return
        
        if not source_path:
            messagebox.showerror("错误", "请选择源目录")
            return
        
        if not os.path.exists(source_path):
            messagebox.showerror("错误", "源目录不存在")
            return
        
        if not repo_url:
            messagebox.showerror("错误", "请输入仓库地址")
            return
        
        # 添加任务
        success, message = self.backup_manager.add_task(
            name=task_name,
            source_path=source_path,
            repo_url=repo_url,
            branch=branch,
            scheduled=self.scheduled_var.get(),
            schedule_time=schedule_time,
            username=username,
            email=email,
            exclude_patterns=exclude_patterns,
            incremental=self.incremental_var.get(),
            resume_transfer=self.resume_var.get(),
            large_file_chunk=self.large_file_var.get()
        )
        
        if success:
            messagebox.showinfo("成功", message)
            self.reset_form()
            self.load_tasks()
            # 切换到任务管理页
            self.notebook.select(0)
        else:
            messagebox.showerror("错误", message)
    
    def reset_form(self):
        """重置表单"""
        self.task_name_entry.delete(0, tk.END)
        self.source_path_entry.delete(0, tk.END)
        self.repo_url_entry.delete(0, tk.END)
        self.branch_entry.delete(0, tk.END)
        self.branch_entry.insert(0, "main")
        self.username_entry.delete(0, tk.END)
        self.email_entry.delete(0, tk.END)
        self.schedule_time_entry.delete(0, tk.END)
        self.schedule_time_entry.insert(0, "03:00")
        self.scheduled_var.set(False)
        self.incremental_var.set(True)
        self.resume_var.set(True)
        self.large_file_var.set(True)
        self.exclude_text.delete(1.0, tk.END)
        self.exclude_text.insert(tk.END, 
            """.git
.svn
.idea
.vscode
.DS_Store
__pycache__
node_modules
vendor
cache
tmp
logs
uploads
backup
temp
runtime
storage
*.zip
*.rar
*.7z
*.tar.*
*.gz
*.bz2
*.log
*.tmp
*.sql
*.bak
*.cache
*.swp
*.pid
*.lock
*.sock
*.session"""
        )
    
    def run_selected_task(self):
        """运行选中的任务"""
        selection = self.tasks_tree.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个任务")
            return
        
        task_id = selection[0]
        success, message = self.backup_manager.run_task(task_id, self.update_task_status)
        
        if success:
            messagebox.showinfo("成功", message)
        else:
            messagebox.showerror("错误", message)
    
    def stop_selected_task(self):
        """停止选中的任务"""
        selection = self.tasks_tree.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个任务")
            return
        
        task_id = selection[0]
        success, message = self.backup_manager.stop_task(task_id)
        
        if success:
            messagebox.showinfo("成功", message)
        else:
            messagebox.showerror("错误", message)
    
    def delete_selected_task(self):
        """删除选中的任务"""
        selection = self.tasks_tree.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择一个任务")
            return
        
        task_id = selection[0]
        task = self.backup_manager.get_task(task_id)
        if not task:
            return
        
        # 确认删除
        result = messagebox.askyesno(
            "确认删除",
            f"确定要删除任务 '{task.name}' 吗？此操作不可撤销。"
        )
        
        if result:
            success, message = self.backup_manager.delete_task(task_id)
            
            if success:
                messagebox.showinfo("成功", message)
                self.load_tasks()
            else:
                messagebox.showerror("错误", message)
    
    def view_task_log(self):
        """查看任务日志"""
        task_name = self.task_selector.get()
        if not task_name:
            messagebox.showwarning("警告", "请先选择一个任务")
            return
        
        # 查找任务
        task_id = None
        for task in self.backup_manager.tasks:
            if task.name == task_name:
                task_id = task.id
                break
        
        if not task_id:
            messagebox.showerror("错误", "任务不存在")
            return
        
        # 获取日志
        log_content = self.backup_manager.get_task_logs(task_id)
        
        # 显示日志
        self.log_text.delete(1.0, tk.END)
        self.log_text.insert(tk.END, log_content)
    
    def clear_logs(self):
        """清空日志"""
        self.log_text.delete(1.0, tk.END)
    
    def save_settings(self):
        """保存设置"""
        # 这里可以保存全局设置到配置文件
        messagebox.showinfo("成功", "设置已保存")
    
    def reset_settings(self):
        """重置设置"""
        # 这里可以重置全局设置
        messagebox.showinfo("成功", "设置已重置")
    
    def update_task_status(self, task):
        """更新任务状态"""
        # 在主线程中更新UI
        def update_ui():
            if task.id in self.tasks_tree.get_children():
                status_text = ""
                if task.status == "idle":
                    status_text = "空闲"
                elif task.status == "running":
                    status_text = "运行中"
                elif task.status == "success":
                    status_text = "成功"
                elif task.status == "failed":
                    status_text = "失败"
                
                progress_text = f"{task.progress}%" if task.progress > 0 else "-"
                
                last_backup_text = "-"
                if task.last_backup:
                    try:
                        dt = datetime.fromisoformat(task.last_backup)
                        last_backup_text = dt.strftime("%Y-%m-%d %H:%M")
                    except:
                        last_backup_text = task.last_backup
                
                self.tasks_tree.item(
                    task.id,
                    values=(
                        task.name,
                        task.source_path,
                        task.repo_url,
                        status_text,
                        progress_text,
                        last_backup_text
                    )
                )
                
                # 如果选中的是当前任务，更新详情
                selection = self.tasks_tree.selection()
                if selection and selection[0] == task.id:
                    self.on_task_select(None)
        
        # 在主线程中执行更新
        self.root.after(0, update_ui)
    
    def start_ui_update_thread(self):
        """启动UI更新线程"""
        def update_ui():
            while True:
                # 定期更新任务状态
                for task in self.backup_manager.tasks:
                    if task.status == "running":
                        self.update_task_status(task)
                
                # 每秒更新一次
                threading.Event().wait(1)
        
        # 在后台线程中运行
        ui_update_thread = threading.Thread(target=update_ui, daemon=True)
        ui_update_thread.start()